package com.gitee.xcfyl.simplehttpserver.config;

import com.gitee.xcfyl.simplehttpserver.servlet.HttpServlet;
import lombok.extern.slf4j.Slf4j;

import java.io.FileInputStream;
import java.net.URL;
import java.util.*;

/**
 * SimpleHttpServer的配置类，目前可以配置的信息有服务端启动的端口号，以及
 * 用户指定的Servlet和url路径等信息
 *
 * @author 西城风雨楼
 */
@Slf4j
public class ServerConfig {
    /**
     * 服务器启动时监听的端口号
     */
    private Integer serverPort = 8080;

    /**
     * 存放请求路径和该请求对应的处理Servlet之间的映射关系
     */
    private final Map<String, HttpServlet> urlServletMap = new HashMap<>();

    /**
     * 存放用户编写的配置信息
     */
    private Properties configProperties = new Properties();

    /**
     * 得到用户的配置信息
     *
     * @return 返回配置信息
     */
    public Properties getConfigProperties() {
        return configProperties;
    }

    /**
     * 获取服务器启动端口
     *
     * @return 返回服务器启动端口
     */
    public int getServerPort() {
        return serverPort;
    }

    /**
     * 根据url查找对应的Servlet
     *
     * @param url url
     * @return 返回对应的Servlet
     */
    public HttpServlet getServletByUrl(String url) {
        return urlServletMap.get(url);
    }

    /**
     * 判断某个url是否存在
     *
     * @param url 用户输入的url路径
     * @return 如果存在，返回true，否则返回false
     */
    public boolean containsUrl(String url) {
        return urlServletMap.containsKey(url);
    }

    private static class ServerConfigHolder {
        public final static ServerConfig SERVER_CONFIG_INSTANCE = new ServerConfig();

        static {
            // 在这里面加载相关的服务器配置
            loadServerConfig();
        }

        private static void loadServerConfig() {
            URL resource = ServerConfig.class.getClassLoader().getResource("web.properties");
            if (resource == null) {
                return;
            }
            try (FileInputStream stream = new FileInputStream(resource.getPath())) {
                Properties properties = new Properties();
                properties.load(stream);
                SERVER_CONFIG_INSTANCE.configProperties = properties;
                if (log.isDebugEnabled()) {
                    log.debug("加载配置文件{}", properties);
                }

                Map<String, HttpServlet> servletMap = new HashMap<>(100);
                Map<String, String> urlMap = new HashMap<>(100);
                // 首先解析所有的路径
                for (Object key : properties.keySet()) {
                    String keyPrefix = (String) key;
                    if (keyPrefix.startsWith("url.")) {
                        String[] urlSplit = keyPrefix.split("\\.");
                        urlMap.put(urlSplit[1], (String) properties.get(keyPrefix));
                        if (log.isDebugEnabled()) {
                            log.debug("匹配到一个url: {}", properties.getProperty(keyPrefix));
                        }
                    } else if (keyPrefix.startsWith("servlet.")) {
                        String[] servletSplit = keyPrefix.split("\\.");
                        String servletClassName = properties.getProperty(keyPrefix);
                        if (log.isDebugEnabled()) {
                            log.debug("匹配到一个Servlet配置{}", servletClassName);
                        }

                        // 创建servlet对象
                        HttpServlet servlet = (HttpServlet) Class.forName(servletClassName).newInstance();
                        servletMap.put(servletSplit[1], servlet);
                    } else if ("server.port".equals(keyPrefix)) {
                        String port = (String) properties.get(keyPrefix);
                        if (log.isDebugEnabled()) {
                            log.debug("匹配到一个服务器端口配置: {}", port);
                        }
                        SERVER_CONFIG_INSTANCE.serverPort = Integer.parseInt(port);
                    }
                }
                // 将url和对应的servlet组装起来
                if (servletMap.size() != urlMap.size()) {
                    throw new RuntimeException("配置文件错误");
                }

                for (String servletName : servletMap.keySet()) {
                    if (!urlMap.containsKey(servletName)) {
                        throw new RuntimeException("配置文件错误");
                    }
                    SERVER_CONFIG_INSTANCE.urlServletMap.put(urlMap.get(servletName), servletMap.get(servletName));
                }
                if (log.isDebugEnabled()) {
                    log.debug("最终生成的url和Servlet映射为: {}", SERVER_CONFIG_INSTANCE.urlServletMap);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取ServerConfig的单例对象
     *
     * @return 返回ServerConfig单例对象
     */
    public static ServerConfig getInstance() {
        return ServerConfigHolder.SERVER_CONFIG_INSTANCE;
    }
}
